-- FUNCTION: public.udf_fetchAvailableDates(integer)

DROP FUNCTION public."udf_fetchAvailableDates"(integer);

CREATE OR REPLACE FUNCTION public."udf_fetchAvailableDates"(
	providerid integer)
    RETURNS TABLE("Date" date, "DateNumber" integer, "DayName" character varying, "Status" character) 
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
    ROWS 1000

AS $BODY$
begin
return query
with TotalDates as (
SELECT DISTINCT generate_series( now()::date,now()::date+ interval '12' month, '1 day')::date "Dates" ,
	A."ProviderId",A."ProviderLocationId",A."LocationId"
from "ProviderLocation" A 
JOIN "Location" PL ON A."LocationId" = PL."LocationId" AND PL."Active" = TRUE
JOIN "Practice" P ON P."PracticeId" = PL."PracticeId" AND P."Active" = TRUE
where A."ProviderId"=providerid AND A."Active" IS TRUE

)
,Availability as (
select A."ProviderId",A."ProviderLocationId",A."LocationId",json_array_elements(case when (A."Availability" is null or A."Availability"='') then '[]' else (A."Availability"::json)end) "Availability"
from "ProviderLocation" A 
JOIN "Location" PL ON A."LocationId" = PL."LocationId" AND PL."Active" = TRUE
JOIN "Practice" P ON P."PracticeId" = PL."PracticeId" AND P."Active" = TRUE
	where A."ProviderId"=providerid AND A."Active" IS TRUE 
	--and case when providerLocationId is null then 1=1 else A."ProviderLocationId"=providerLocationId end
)
,Avail as (
select A."ProviderId",A."ProviderLocationId",A."LocationId",A."Availability"->'day' "Day" ,
	A."Availability"->'slots' "Slots"
from Availability A
)

, LeaveAvailability as (
select A."ProviderId",A."LeaveDate",coalesce(A."ProviderLocationId"::text,
(
	select string_agg(D."ProviderLocationId"::text,',') "ProviderLocationId" from "ProviderLocation" D where D."ProviderId"= providerid
))
	"ProviderLocationId" from "ProviderLeave" A where A."ProviderId"=providerid
)
,LeaveData as (
select A."ProviderId",A."LeaveDate",regexp_split_to_table(A."ProviderLocationId",',') ::int "ProviderLocationId" 
	from LeaveAvailability A
)

,FinalData as (
select DISTINCT C."LeaveDate", A."Dates" "Date", A."ProviderId",A."ProviderLocationId",
	A."LocationId",extract(ISODOW from "Dates")"DateNo", CASE
WHEN extract(ISODOW from "Dates") =1 THEN 'Monday'
WHEN extract(ISODOW from "Dates") =2 THEN 'Tuesday'
WHEN extract(ISODOW from "Dates")=3 THEN 'Wednesday'
WHEN extract(ISODOW from "Dates")=4 THEN 'Thursday'
WHEN extract(ISODOW from "Dates")=5 THEN 'Friday'
WHEN extract(ISODOW from "Dates")=6 THEN 'Saturday'
WHEN extract(ISODOW from "Dates")=7 THEN 'Sunday' end "Day" ,
case when C."LeaveDate" is not null then 'L' when B."Day" is not null then 'A' else '' end "Status"
from TotalDates A
left join Avail B on B."Day"::text::int = extract(ISODOW from A."Dates") and A."ProviderId"=A."ProviderId" and A."ProviderLocationId"=B."ProviderLocationId"
and A."LocationId"=B."LocationId"
left join LeaveData C on C."LeaveDate"::date =A."Dates" and A."ProviderLocationId"=C."ProviderLocationId"

)

select DISTINCT A."Date",A."DateNo"::int,A."Day"::text::character varying(10),A."Status"::char
from FinalData A
order by A."Date";
end

$BODY$;

ALTER FUNCTION public."udf_fetchAvailableDates"(integer)
    OWNER TO postgres;
